﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using RuoVea.ExConfig;
using RuoVea.ExJwtBearer;
using RuoVea.ExPws;
using RuoVea.ExPws.Options;
using RuoVea.OmiApi.Config;
using RuoVea.OmiApi.SystemApp.SeedData;
using RuoVea.OmiApi.SystemApp.Service;

namespace RuoVea.OmiApi.SystemApp;
/// <summary>
/// 注入扩展
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 用户、角色、菜单、机构、职位、权限管理
    /// </summary>
    /// <param name="services"></param>
    /// <param name="serviceLifetime">Scoped</param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static IServiceCollection AddOmiSystemSetup(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        services.Configure<DbInitConfig>(AppSettings.Configuration.GetSection("DbInitConfig"));
        return DI(services, null, serviceLifetime);
    }

    /// <summary>
    /// 用户、角色、菜单、机构、职位、权限管理
    /// </summary>
    /// <param name="services"></param>
    /// <param name="config"></param>
    /// <param name="serviceLifetime">Scoped</param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static IServiceCollection AddOmiSystemSetup(this IServiceCollection services, IConfiguration config, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        if (config == null) throw new ArgumentNullException(nameof(config));
        services.Configure<DbInitConfig>(config);
        DbInitConfig dbInitConfig = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
        return DI(services, dbInitConfig, serviceLifetime);
    }

    /// <summary>
    /// 用户、角色、菜单、机构、职位、权限管理
    /// </summary>
    /// <param name="services"></param>
    /// <param name="config"></param>
    /// <param name="serviceLifetime">Scoped</param>
    /// <returns></returns>
    /// <exception cref="ArgumentNullException"></exception>
    public static IServiceCollection AddOmiSystemSetup(this IServiceCollection services, Action<DbInitConfig> config, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
    {
        if (services == null) throw new ArgumentNullException(nameof(services));
        if (config == null) throw new ArgumentNullException(nameof(config));
        services.Configure(config);
        DbInitConfig dbInitConfig = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
        return DI(services, dbInitConfig, serviceLifetime);
    }

    #region DI
    private static IServiceCollection DI(IServiceCollection services, DbInitConfig dbInitConfig, ServiceLifetime serviceLifetime)
    {
        services.AddJwtSetup();
        services.Configure<PasswordConfig>(AppSettings.Configuration.GetSection("PasswordConfig"));
        //services.AddCaptcha(AppSettings.Configuration);

        switch (serviceLifetime)
        {
            case ServiceLifetime.Scoped:
                services.AddScoped<SysCacheService>();
                services.AddScoped<SysMenuService>();
                services.AddScoped<SysOrgService>();
                services.AddScoped<SysPosService>();
                services.AddScoped<SysUserExtOrgService>();
                services.AddScoped<SysRoleMenuService>();
                services.AddScoped<SysRoleService>();
                services.AddScoped<SysRoleOrgService>();
                services.AddScoped<SysRoleService>();
                services.AddScoped<SysUserRoleService>();
                services.AddScoped<SysUserService>();
                services.AddScoped<IPasswordServer>();
                break;
            case ServiceLifetime.Singleton:
                services.AddSingleton<SysCacheService>();
                services.AddSingleton<SysMenuService>();
                services.AddSingleton<SysOrgService>();
                services.AddSingleton<SysPosService>();
                services.AddSingleton<SysUserExtOrgService>();
                services.AddSingleton<SysRoleMenuService>();
                services.AddSingleton<SysRoleService>();
                services.AddSingleton<SysRoleOrgService>();
                services.AddSingleton<SysRoleService>();
                services.AddSingleton<SysUserRoleService>();
                services.AddSingleton<SysUserService>();
                services.AddSingleton<IPasswordServer>();
                break;
            case ServiceLifetime.Transient:
                services.AddTransient<SysCacheService>();
                services.AddTransient<SysMenuService>();
                services.AddTransient<SysOrgService>();
                services.AddTransient<SysPosService>();
                services.AddTransient<SysUserExtOrgService>();
                services.AddTransient<SysRoleMenuService>();
                services.AddTransient<SysRoleService>();
                services.AddTransient<SysRoleOrgService>();
                services.AddTransient<SysRoleService>();
                services.AddTransient<SysUserRoleService>();
                services.AddTransient<SysUserService>();
                services.AddTransient<IPasswordServer>();
                break;
        }
        services.AddOmiConfigSetup((o) => { o = dbInitConfig; }, serviceLifetime);
        return services;
    }
    #endregion

    /// <summary>
    /// 用户、角色、菜单、机构、职位、权限管理 - 初始化数据库/初始化种子数据
    /// </summary>
    /// <param name="services"></param>
    /// <param name="isWeb">是否Web菜单/false:api菜单</param>
    /// <returns></returns>
    public static IServiceCollection AddSystemInitSetup(this IServiceCollection services,bool isWeb=false)
    {
        Task.Run(() =>
        {
            services.AddConfigInitSetup();
            DbInitConfig config = services.BuildServiceProvider().GetRequiredService<IOptions<DbInitConfig>>()?.Value;
            var _thisRepository = services.BuildServiceProvider().GetRequiredService<ISqlSugarClient>();
            if (config.InitTable && _thisRepository != null)
            {
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysMenu), false) || _thisRepository.DbMaintenance.IsAnyTable("sys_menu", false)) { }else
                {
                    _thisRepository.CodeFirst.InitTables<SysMenu>();
                    if (config.InitSeedData) {
                        if (isWeb) 
                            _thisRepository.Storageable(new SysMenu_SeedData().HasDataWeb().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                        else
                            _thisRepository.Storageable(new SysMenu_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                    }
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysOrganization), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_organization", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysOrganization>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysOrganization_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysPosition), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_position", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysPosition>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysPosition_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }


                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysRole), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_role", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysRole>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysRole_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysRoleMenu), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_role_menu", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysRoleMenu>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysRoleMenu_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysRoleOrg), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_role_org", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysRoleOrg>();
                    //if (config.InitSeedData)
                    //    _thisRepository.Insertable(new SysRoleDataScopeSeedData().HasData().ToList()).ExecuteCommand();
                }


                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysUser), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_user", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysUser>();
                    if (config.InitSeedData)
                    {
                        PasswordConfig passwordConfig = services.BuildServiceProvider().GetRequiredService<IOptions<PasswordConfig>>()?.Value;
                        IPasswordServer passwordServer = services.BuildServiceProvider().GetRequiredService<IPasswordServer>();
                        var seedData = new SysUser_SeedData().HasData().ToList();
                        string defaultEncryptPassword = passwordServer.Encrypt(passwordConfig.DefaultPassword);
                        seedData.ForEach(x => x.Password = defaultEncryptPassword);
                        _thisRepository.Storageable(seedData).ToStorage().AsInsertable.ExecuteCommand();
                    }
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysUserRole), false) || _thisRepository.DbMaintenance.IsAnyTable("sys_user_role", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysUserRole>();
                    if (config.InitSeedData)
                        _thisRepository.Storageable(new SysUserRole_SeedData().HasData().ToList()).ToStorage().AsInsertable.ExecuteCommand();
                }
                if (_thisRepository.DbMaintenance.IsAnyTable(nameof(SysUserExtOrg), false)|| _thisRepository.DbMaintenance.IsAnyTable("sys_user_ext_org", false)) { }
                else
                {
                    _thisRepository.CodeFirst.InitTables<SysUserExtOrg>();
                    if (config.InitSeedData)
                        _thisRepository.Insertable(new SysUserExtOrg_SeedData().HasData().ToList()).ExecuteCommand();
                }
            }
        });
        return services;
    }
}
